﻿using Cofe.Core.Service;
using Cofe.Core.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cofe.Core.Implements
{
    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFE)]
    public class ServiceLocater : IServiceLocater
    {
        #region Constructor

        public ServiceLocater()
        {

        }

        public ServiceLocater(IServiceImporter importer)
        {
            lock (_services)
                _services = importer.ImportServices().ToList();
        }

        #endregion

        #region Methods

        public T TryFindService<T>()
        {
            return FindAllServices<T>().FirstOrDefault();
        }

        public T FindService<T>()
        {
            T found = TryFindService<T>();
            if (found == null)
                throw new KeyNotFoundException(typeof(T).ToString() + " cannot be found.");
            return found;
        }

        public IEnumerable<T> FindAllServices<T>(Func<T, bool> filter = null)
        {
            lock (_services)
            {
                if (filter != null)
                    return (from s in _services
                            where s is T
                            select (T)s)
                        .Where(s => filter(s))
                        .OrderByDescending((s) =>
                            ServicePriorityAttribute.GetPriority(s)).ToList();


                return (from s in _services
                        where s is T
                        select (T)s).
                        OrderByDescending((s) =>
                            ServicePriorityAttribute.GetPriority(s)).ToList();
            }
        }

        public void Register(IEnumerable<ICofeService> services)
        {
            _services.AddRange(services);
        }


        #endregion

        #region Data

        private List<ICofeService> _services = new List<ICofeService>();

        #endregion

        #region Public Properties

        #endregion

    }
}
